﻿using System;
using System.Collections.Generic;

namespace DKE_Kinect.Entwicklung.Grafik.ControlManaging
{
	public abstract class Item
	{
		private ActivationType pActionType;
		private Action pOnAction;

		private string pText; // Anzeige - Text
		private int pSelectedIndex; // Ausgewähltes Element
		private int pCollapsedIndex;

		/// <summary>
		/// Auszuführende Methode beim Aktivieren des Menüpunktes.
		/// </summary>
		public Action Action { get { return this.pOnAction; } set { this.pOnAction = value; } }
		/// <summary>
		/// Typ der Aktivierung.
		/// </summary>
		public ActivationType ActivationType { get { return this.pActionType; } set { this.pActionType = value; } }

		/// <summary>
		/// Gibt an, welcher Untermenüpunkt dieses Menüpunktes ausgewählt wurde oder legt diesen fest.
		/// </summary>
		public int SelectedIndex { get { return this.pSelectedIndex; } set { this.pSelectedIndex = value; } }
		/// <summary>
		/// Gibt an, welche Untermenüpunkt ausgeklappt wurde oder legt diesen fest.
		/// </summary>
		public int CollapsedIndex { get { return this.pCollapsedIndex; } set { this.pCollapsedIndex = value; } }
	}

	/// <summary>
	/// Repräsentiert ein Menüpunkt.
	/// </summary>
	public class MenuItem : IMenu<MenuItem>
	{
		#region Fields

		private ActivationType pActionType;

		private string pText; // Anzeige - Text
		private IMenu<MenuItem> pParent; // Übergeordnetes Menü
		private List<MenuItem> pSubItems; // Untergeordnete Menüs

		private int pSelectedIndex; // Ausgewähltes Element
		private Action pOnAction;

		private int pCollapsedIndex;

		#endregion

		public MenuItem (IMenu<MenuItem> Parent)
		{
			if (Parent == null)
				throw new ArgumentNullException();

			this.pSubItems = new List<MenuItem>();
			this.pParent = Parent;
			this.pSelectedIndex = -1;
			this.pCollapsedIndex = -1;
		}

		/// <summary>
		/// Instanziiert ein neues Objekt dieser Klasse.
		/// </summary>
		/// <param name="Text">Label.</param>
		/// <param name="Parent">Übergeordneter Menüpunkt.</param>
		public MenuItem (string Text, IMenu<MenuItem> Parent)
			: this(Text, ActivationType.LayerForward, Parent)
		{ }
		/// <summary>
		/// Instanziiert ein neues Objekt dieser Klasse.
		/// </summary>
		/// <param name="Text">Label.</param>
		/// <param name="Type">Typ des Menüpunktes, der beim aktivieren unterschiedlich reagiert. (Siehe <see cref="ActivationType"/>)</param>
		/// <param name="Parent">Übergeordneter Menüpunkt.</param>
		public MenuItem (string Text, ActivationType Type, IMenu<MenuItem> Parent)
			: this(Parent)
		{
			if (Type == ActivationType.LayerForward)
				this.pSubItems.Add(new MenuItem(" < Zurück < ", ActivationType.LayerBackward, this));
			//else if ((Type == ActivationType.LayerBackward) && (this.pParent == null))
			//  throw new ArgumentException();

			this.pText = Text;
			this.pActionType = Type;
			this.pOnAction = null;
		}
		/// <summary>
		/// Instanziiert ein neues Objekt dieser Klasse.
		/// </summary>
		/// <param name="Text">Label.</param>
		/// <param name="OnActivation">Auszuführende Aktion beim Aktivieren des Menüpunktes.</param>
		/// <param name="Parent">Übergeordneter Menüpunkt.</param>
		public MenuItem (string Text, Action OnActivation, IMenu<MenuItem> Parent)
			: this(Parent)
		{
			this.pText = Text;
			this.pActionType = ActivationType.OwnDelegate;
			this.pOnAction = OnActivation;
		}

		#region Properties

		/// <summary>
		/// Auszuführende Methode beim Aktivieren des Menüpunktes.
		/// </summary>
		public Action Action { get { return this.pOnAction; } set { this.pOnAction = value; } }
		/// <summary>
		/// Typ der Aktivierung.
		/// </summary>
		public ActivationType ActivationType { get { return this.pActionType; } set { this.pActionType = value; } }

		/// <summary>
		/// Gibt den Index dieses Menüpunktes gegenüber dem übergeordneten Menü an.
		/// </summary>
		public int Index
		{
			get
			{
				for (int i = 0; i < this.pSubItems.Count; i++)
					if (object.ReferenceEquals(this, this.pParent.SubItems[i]))
						return i;

				return -1;
			}
		}
		/// <summary>
		/// Gibt an, welcher Untermenüpunkt dieses Menüpunktes ausgewählt wurde oder legt diesen fest.
		/// </summary>
		public int SelectedIndex { get { return this.pSelectedIndex; } set { this.pSelectedIndex = value; } }
		/// <summary>
		/// Gibt an, welche Untermenüpunkt ausgeklappt wurde oder legt diesen fest.
		/// </summary>
		public int CollapsedIndex { get { return this.pCollapsedIndex; } set { this.pCollapsedIndex = value; } }

		/// <summary>
		/// Gibt an, ob dieser Menüpunkt der Knoten / Wurzel des Menübaumes ist.
		/// </summary>
		public bool Root { get { return false; } }
		/// <summary>
		/// Gibt den übergeordneten Knoten dieses Menüpunktes an.
		/// </summary>
		public IMenu<MenuItem> PreviousLayer { get { return this.pParent; } }
		/// <summary>
		/// Gibt alle untergeordneten Menüpunkte an.
		/// </summary>
		public List<MenuItem> SubItems { get { return this.pSubItems; } }

		/// <summary>
		/// Gibt den ausgewählten Menüpunkt an.
		/// </summary>
		public MenuItem SelectedItem { get { return (this.pSelectedIndex < 0) ? null : this.pSubItems[this.pSelectedIndex]; } }

		/// <summary>
		/// Gibt den Text an, den dieser Menüpunkt darstellen soll oder legt diesen fest.
		/// </summary>
		public string Text { get { return this.pText; } set { this.pText = value; } }

		#endregion

		/// <summary>
		/// Selektiert diesen Menüpunkt.
		/// </summary>
		public void Select ()
		{
			throw new NotImplementedException();
		}
		/// <summary>
		/// Gibt den Wurzelknoten im Menübaum an.
		/// </summary>
		/// <returns></returns>
		public IMenu<MenuItem> GetRoot ()
		{
			return this.pParent.GetRoot();
		}
	}

	/// <summary>
	/// Stellt Möglichkeiten dar, welche Art der Aktion beim Aktivieren eines Menüpunktes ausgeführt werden soll.
	/// </summary>
	public enum ActivationType
	{
		/// <summary>
		/// Beim Aktivieren wird eine Ebene tiefer in das Menü eingeblendet.
		/// </summary>
		LayerForward = 0,
		/// <summary>
		/// Beim Aktivieren wird die aktuelle Ebene aus dem Menü ausgeblendet.
		/// </summary>
		LayerBackward = 1,
		/// <summary>
		/// Beim Aktivieren wird eine eigene Methode ausgeführt.
		/// </summary>
		OwnDelegate = 2,
		/// <summary>
		/// Das Menüitem wird selektiert oder deselektiert.
		/// </summary>
		Activation = 3
	}
}
